import { Event } from "socket.io/dist/socket";
import { RequestMethod } from "../src/lib/defines";
import { IMember, MemberBase, RoomBase } from "../src/utils/types";
import { Member, Members } from '../src/lib/Member';
import { Room, Classrooms } from '../src/lib/Classrooms';
import { isType } from "../src/utils/utils";
import { ChatRoomEntity } from "../src/httpServer/entity/ChatRoomEntity";
import { NoticeEntity } from "../src/httpServer/entity/NoticeEntity";
import { taggleAccountState } from '../src/request/account-api'

type TOption = {
  owner?: IMember
  rooms?: RoomBase[]
  members?: MemberBase[]
}

// power: 权力;能力;控制力;影响力;操纵力;
// authority: 权威;权力;权;授权;职权;威权;当权(地位);
export default function login (app) {
  const { socket } = app.locals;
  const { userId, username } = socket.handshake.query;

  /**
   * 用户登录时
   * 查询未读通知，全部推送给对方。
   */
  socket.use(async (event: Event, next: (err?: Error) => void) => {
    const [name, params] = event

    if (name === RequestMethod.login) {
      const notice = await NoticeEntity.findBy({ receiverId: userId, state: "UNREAD" })

      if (Array.isArray(notice) && notice.length) {
        for (const __notice of notice) {
          let dbNotice = Object.assign(new NoticeEntity(), __notice, {
            state: 'READ'
          })

          dbNotice = await dbNotice.save()

          socket.emit('notice:message', dbNotice)
        }
      }
    }

    next()
  })


  /**
   * 用户上线后 - 登录
   *
   * 如果用户上线时，传入了 classId 则，默认为用户 创建/加入 常驻房间
   *
   * TODO 用于 创建/加入 常驻房间
   * @params classId 常驻房间 ID
   * @params classname 常驻房间 ID
   */
  socket.on(RequestMethod.login, async function({ rooms, members }: TOption, cb) {
    const owner = { userId, username }
    let memberBroadcast: MemberBase[] = []
    let classMember = Members.get(userId)

    if (!classMember) {
      return cb && cb(socket.errorMsg('login', 'member not find!'))
    }

    console.log('login: =>', 'user', { userId, username })
    console.log('login: =>', '通知 rooms', rooms)
    if (isType(rooms, 'array')) {
      (rooms as RoomBase[]).forEach(({ classId }) => {
        const room = Classrooms.get(classId);
        classMember.setClassroom(classId)

        if (room) {
          const __members: Member[] = room.getMembers(true)
          // members.forEach((__member: Member) => __members.push(__member.json()))
          memberBroadcast = memberBroadcast.concat(__members)

          // 通知当前房间的其他人，但是自己并不收到消息
          socket.broadcast.to(classId).emit('member:online', owner as any);
        }
      });
    }

    console.log('login: =>', '通知 members', members)
    if (isType(members, 'array')) {
      (members as MemberBase[]).forEach(({ userId }) => {
        classMember.setAudience(userId)
        // const __member = app.locals.members[]
        const __member = Members.get(userId)

        if (__member) {
          if (Classrooms.has(__member.classId)) {
            // 如果在房间中，已经通知了，这里不再单独通知。
            return;
          }

          console.log('member:online: =>', __member)
          memberBroadcast.push(__member)
          // intercom[__member.userId].emit('member:online', owner as any);
          socket.to(__member.socketId).emit('member:online', owner as any);
        }
      });
    }

    // 查询用户所在的房间列表
    const data = await ChatRoomEntity.createQueryBuilder('member_chat_room')
      .leftJoinAndSelect("member_chat_room.classroom", "classroom")
      .where("member_chat_room.userId=:userId", { userId })
      .getMany()

    if (Array.isArray(data)) {
      // 加入所有房间
      for (const person of data) {
        const { classId, classname } = person.classroom as any
        socket.join(classId)
        socket.emit('join:chart-room', { classId, classname })
        console.log('join: => ', { classId, classname })
      }
    }

    // 回调
    if (cb) {
      /*const allMembers = [...Rooms.values()].reduce((defRoom: any[], room: Room) => {
        defRoom = defRoom.concat(room.getMembers(true))
        return defRoom
      }, [])*/
      // console.log([...Rooms.values()])
      cb({
        status: 'ok',
        resolve: '[response]:logged',
        members: Members.toArray(),
        broadcast: memberBroadcast
      })
    }
  });
}
